from django.shortcuts import render
from meiduo_mall.utils.views import LoginRequiredView
from django import http
from users.models import Address
from django_redis import get_redis_connection
from decimal import Decimal
import json
from .models import OrderGoods, OrderInfo
import logging
from django.utils import timezone
from goods.models import SKU
from meiduo_mall.utils.response_code import RETCODE
from django.db import transaction

logger = logging.getLogger('django')
# Create your views here.

class OrderSettlementView(LoginRequiredView):

    def get(self, request):

        user = request.user
        address_qs = Address.objects.filter(user=user, is_deleted=False)

        redis_conn = get_redis_connection('carts')
        redis_carts = redis_conn.hgetall('cart_%s' % user.id)
        selected_ids = redis_conn.smembers('selected_%s' % user.id)
        cart_dict = {}

        for sku_id_bytes in selected_ids:
            cart_dict[int(sku_id_bytes)] = int(redis_carts[sku_id_bytes])

        sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
        total_count = 0
        total_amount = Decimal('0.00')

        for sku in sku_qs:
            sku.count = cart_dict[sku.id]
            sku.amount = sku.price * sku.count
            total_count += sku.count
            total_amount += sku.amount
        freight = Decimal('10.00')

        context = {
            'addresses': address_qs,
            'skus': sku_qs,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight
        }

        return render(request, 'place_order.html', context)


class OrderCommitView(LoginRequiredView):

    def post(self, request):

        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        if all([address_id, pay_method]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        user = request.user
        try:
            address = Address.objects.get(id=address_id, user=user, is_deleted=False)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('address_id有误')
        # if not (pay_method == '1' or pay_method == '2'):
        try:
            pay_method = int(pay_method)
            if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
                return http.HttpResponseForbidden('支付方式有误')
        except Exception as e:
            logger.error(e)
            return http.HttpResponseForbidden('支付方式有误')

        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id
        status = (OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND'])

        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id = order_id,
                    user = user,
                    address = address,
                    total_count = 0,
                    total_amount = Decimal('0.00'),
                    freight = Decimal('10.00'),
                    pay_method = pay_method,
                    status = status
                )
                redis_conn = get_redis_connection('carts')
                redis_carts = redis_conn.hgetall('cart_%s' % user.id)
                selected_ids = redis_conn.smembers('selected_%s' % user.id)
                cart_dict = {}
                for sku_id_bytes in selected_ids:
                    cart_dict[int(sku_id_bytes)] = int(redis_carts[sku_id_bytes])

                # sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
                for sku_id in cart_dict:

                    while True:
                        sku = SKU.objects.get(id = sku_id)
                        buy_count = cart_dict[sku_id]
                        origin_stock = sku.stock
                        origin_sales = sku.sales
                        if buy_count > origin_stock:
                            transaction.savepoint_rollback(save_point)
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})

                        new_stock = origin_stock - buy_count
                        new_sales = origin_sales + buy_count
                        # sku.stock = new_stock
                        # sku.sales = new_sales
                        # sku.save()
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
                        if result == 0:
                            continue
                        spu = sku.spu
                        spu.sales += buy_count
                        spu.save()

                        OrderGoods.objects.create(
                            order = order,
                            sku = sku,
                            count = buy_count,
                            price = sku.price
                        )

                        order.total_count += buy_count
                        order.total_amount += (sku.price * buy_count)
                        break

                order.total_amount += order.freight
                order.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_point)
                return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '下单失败'})
            else:
                transaction.savepoint_commit(save_point)

        pl = redis_conn.pipeline()
        pl.hdel('cart_%s' % user.id, *selected_ids)
        pl.delete('selected_%s' % user.id)
        pl.execute()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '提交订单成功', 'order_id': order_id})


class OrderSuccessView(LoginRequiredView):

    def get(self, request):

        query_dict = request.GET
        payment_amount = query_dict.get('payment_amount')
        order_id = query_dict.get('order_id')
        pay_method = query_dict.get('pay_method')
        try:
            OrderInfo.objects.get(order_id=order_id, total_amount=payment_amount, pay_method=pay_method, user=request.user)
        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('订单信息有误')
        context = {
            'payment_amount': order_id,
            'order_id': payment_amount,
            'pay_method': pay_method,
        }

        return render(request, 'order_success.html', context)


class GoodsCommentsView(LoginRequiredView):
    """订单评价"""

    def get(self, request):
        # 接收order_id
        order_id = request.GET.get('order_id')
        # 获取用户订单查询集
        order_qs = OrderGoods.objects.filter(order_id=order_id, is_commented=False)
        # 获取商品ID
        # 将查询出的sku_id保存在一个列表里
        sku_id_list = []
        for sku_model in order_qs:
            sku_id_list.append(sku_model.sku_id)

        # 查询商品模型
        sku_qs = SKU.objects.filter(id__in=sku_id_list)
        # 包装返回数据
        context = list()
        for sku in sku_qs:
            context.append(
                {
                    'name': sku.name,
                    'price': str(sku.price),
                    'default_image_url': sku.default_image.url,
                    'order_id': order_id,
                    'sku_id': sku.id
                }
            )
        # 响应
        return render(request, 'goods_judge.html', {'uncomment_goods_list': context})

    def post(self, request):
        # 接收请求体非表单数据
        json_dict = json.loads(request.body.decode())
        order_id = json_dict.get('order_id')
        sku_id = json_dict.get('sku_id')
        comment = json_dict.get('comment')
        score = json_dict.get('score')
        is_anonymous = json_dict.get('is_anonymous')

        # 校验数据
        user = request.user

        if all([order_id, sku_id, comment, score]) is False:
            return http.HttpResponseForbidden("缺少必传参数")

        try:
            SKU.objects.get(id=sku_id, is_launched=True)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('sku_id不存在')

        try:
            OrderInfo.objects.get(order_id=order_id, user=user, status=4)
        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('订单信息有误')

        if len(comment) <= 5:
            return http.HttpResponseForbidden("请填写多于5个字的评价内容")

        if isinstance(score, int) is False:
            return http.HttpResponseForbidden("参数类型错误")

        if isinstance(is_anonymous, bool) is False:
            return http.HttpResponseForbidden("参数类型错误")

        is_commented = True
        try:
            # 修改订单信息记录
            OrderGoods.objects.filter(order_id=order_id, sku_id=sku_id).update(
                comment=comment,
                score=score,
                is_anonymous=is_anonymous,
                is_commented=True
            )

            order_is_commented = OrderGoods.objects.filter(order_id=order_id)
            for order_commented in order_is_commented:
                if not order_commented.is_commented:
                    is_commented = False

            if is_commented:
                OrderInfo.objects.filter(order_id=order_id, user=user,
                                         status=OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT']).update(
                status=OrderInfo.ORDER_STATUS_ENUM['FINISHED'])
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '提交评价失败'})

        # 创建redis连接对象
        redis_conn = get_redis_connection('comments')

        # 写入hash数据
        redis_conn.hset(f'comments_{sku_id}', score, comment)

        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '评价成功'})







